import {Modal} from 'ant-design-vue';
import $ from 'jquery';
import {
  canDragin,
  createDraginRootPlaceholder,
  createFieldBarWrapper,
  createFieldWrapper,
  createLayoutBarContainer,
  createSubTableByConfig, dragShadowImgMousemove,
  getBarAction,
  getElementParentUntilHasRole,
  getElementParentUntilTag,
  getFieldConfigById,
  getFieldId,
  getSubFormById,
  getSubFormIdByLayoutElement,
  getSubTableId,
  getSubTableRole,
  isEmptyContent,
  isRole,
  isSubFormField,
  isSubTable,
  setSelectFieldStyle, startDragShadowImg,
  stop, stopDragShadowImg
} from '@/utils/FormDesignUtils';
import {getFieldComponent} from '@/components/hhd/design/FormDesigner/field/comps/FieldRegister';
import {createSubTable} from '@/components/hhd/design/FormDesigner/types';
import {hideTd, showTd} from '@/components/hhd/design/DesignTable/TableHelper';

const constant = {
  designRoot: 'design-root',
  field: 'field',
  layout: 'layout',
  content: 'content',
  move: 'move',
  subTable: 'subTable',
  subTableHeader: 'header',
  subTableBody: 'body',
  subTableFooter: 'footer',
  placeholder: 'placeholder',
  fieldContainer: 'field-container',
  fieldComponent: 'field-component',
  layoutComponent: 'layout-component',
  dragBarAction: 'drag-bar-action',
  fieldDefinition: 'field-definition',
  subFormDefinition: 'sub-form-definition',
  ignoreSelectField: 'ignore-select-field',
  customComponent: 'custom-component',
};

export default class {
  root;
  config;
  formDefinition;
  formDesignAction;
  rebind;

  constructor(formDesignAction) {
    this.formDesignAction = formDesignAction;
    let {root, config, formDefinition} = formDesignAction;
    this.root = root;
    this.config = config;
    this.formDefinition = formDefinition;
  }

  bind({reBind}) {
    this.reBind = reBind;
    this.bindDragFieldComponentAndField();
    this.bindDragField();
    this.bindDragLayout();
    this.bindDragBarAction();
    this.bindSelectField();
    this.bindFieldTitles();
    this.bindDragSubFormDefinition();
    this.bindCustomComponents();
    this.removeRedundantFields();
    this.removeRedundantSubForms();
    this.resolveSubFormButtonContainer();
    return this;
  }

  bindDragFieldComponentAndField() {
    let that = this;

    function dragstart({target}) {
      let el = getElementParentUntilHasRole(target, constant.fieldComponent);
      el = el || getElementParentUntilHasRole(target, constant.layoutComponent);
      el = el || getElementParentUntilHasRole(target, constant.fieldDefinition);
      if (isRole(el, constant.fieldComponent)) that.bindDragFieldComponent(el);
      if (isRole(el, constant.layoutComponent)) that.bindDragLayoutComponent(el);
      if (isRole(el, constant.fieldDefinition)) that.bindDragFieldDefinition(el);
    }

    this.findFieldContainer().off('dragstart').on('dragstart', dragstart);
  }

  bindDragField() {
    let that = this, dragging = undefined, placeholder = undefined;
    let fieldId = undefined, dragended = false;

    function dragend(e) {
      dragended = true;
      stopDragShadowImg();
      $(dragging).removeClass('is-moving');
      that.findDesignRoot().off('dragover');
      that.findDesignRoot().off('dragend');
      if (!placeholder || !placeholder.parentNode) return;
      $(placeholder).replaceWith(dragging);
      that.reBind && that.reBind();
    }

    function dragover(e) {
      dragShadowImgMousemove(e);
      let {target} = e, el = undefined;
      el = getElementParentUntilHasRole(target, constant.content);
      el = el || getElementParentUntilHasRole(target, constant.placeholder);
      el = el || getElementParentUntilHasRole(target, constant.field);
      el = el || getElementParentUntilHasRole(target, constant.layout);
      el = el || getElementParentUntilHasRole(target, constant.designRoot);
      if (!dragging) return;
      if (el === dragging) {
        $(placeholder).remove();
        return;
      }
      placeholder = placeholder || createDraginRootPlaceholder();
      if (isRole(el, constant.content)) {
        let layout = getElementParentUntilHasRole(el, constant.layout);
        let rect = layout.getBoundingClientRect();
        if (rect.y + 15 > e.clientY) {
          //比较靠上
          if ($(layout).prev()[0] === dragging) return;
          if (isSubFormField(fieldId, that.formDefinition)) {
            $(placeholder).remove();
            return;
          }
          $(layout).before(placeholder);
        } else {
          //比较靠下
          // if ($(target).children().length === 0) {
          if (isEmptyContent(el)) {
            if (canDragin(el, fieldId, that.formDefinition)) {
              $(el).append(placeholder);
            } else {
              $(placeholder).remove();
              return;
            }
          } else {
            $(placeholder).remove();
          }
        }
      }
      if (isRole(el, constant.designRoot)) {
        if (isSubFormField(fieldId, that.formDefinition)) {
          $(placeholder).remove();
          return;
        }
        let rect = el.getBoundingClientRect();
        if (rect.y + 20 > e.clientY) {
          //比较靠上
          if (that.findDesignRoot().children().first()[0] === dragging) {
            return;
          }
          that.findDesignRoot().prepend(placeholder);
        } else {
          //比较靠下
          if (that.findDesignRoot().children().last()[0] === dragging) {
            return;
          }
          that.findDesignRoot().append(placeholder);
        }
        // that.findDesignRoot().append(placeholder);
      }
      if (isRole(el, constant.field) || isRole(el, constant.layout)) {
        if (isSubFormField(fieldId, that.formDefinition)) {
          $(placeholder).remove();
          return;
        }

        let rect = el.getBoundingClientRect();
        if (rect.y + 15 > e.clientY) {
          //比较靠上
          if ($(el).prev()[0] === dragging) return;
          $(el).before(placeholder);
        } else {
          //比较靠下
          if ($(el).next()[0] === dragging) return;
          $(el).after(placeholder);
        }
      }
      stop(e);
    }

    function dragstart(e) {
      let {target} = e
      dragging = getElementParentUntilHasRole(target, constant.field);
      fieldId = getFieldId(dragging);
      if (!dragging || !fieldId) return;
      dragended = false;
      setTimeout(() => {
        if (!dragended) {
          $(dragging).addClass('is-moving');
        }
      }, 200);
      that.findDesignRoot().off('dragover').on('dragover', dragover);
      that.findDesignRoot().off('dragend').on('dragend', dragend);
      startDragShadowImg(e, dragging);
    }

    this.findDesignRoot().find('[data-role=' + constant.field + ']').off('mousedown').on('mousedown', e => {
      e.stopPropagation();
    });
    this.findDesignRoot().off('dragstart').on('dragstart', dragstart);
  }

  bindDragLayout() {
    let dragging = undefined, placeholder = undefined, that = this;

    function dragend(e) {
      stopDragShadowImg();
      $(dragging).removeClass('is-moving');
      if (!placeholder || !placeholder.parentNode) return;
      $(placeholder).replaceWith(dragging);
      that.reBind && that.reBind();

      $(document.body).off('dragover');
      that.findDesignRoot().off('dragend');
    }

    function dragover(e) {
      dragShadowImgMousemove(e);
      let {target} = e;
      let el = getElementParentUntilHasRole(target, constant.layout);
      el = el || getElementParentUntilHasRole(target, constant.field);
      el = el || getElementParentUntilHasRole(target, constant.placeholder);
      if (!el || dragging === el) {
        $(placeholder).remove();
        return;
      }
      if (isRole(el, constant.placeholder)) {
        stop(e);
        return;
      }
      placeholder = placeholder || createDraginRootPlaceholder();
      if (isRole(el, constant.field) || isRole(el, constant.layout)) {
        let rect = el.getBoundingClientRect();
        if (rect.y + 15 > e.clientY) {
          //比较靠上
          if ($(el).prev()[0] === dragging) return;
          $(el).before(placeholder);
        } else {
          //比较靠下
          if ($(el).next()[0] === dragging) return;
          $(el).after(placeholder);
        }
        stop(e);
      }
    }

    function dragstart(e) {
      let {target} = e;
      let el = getElementParentUntilHasRole(target, constant.layout);
      if (!el) return;
      dragging = el;
      $(dragging).addClass('is-moving');

      $(document.body).off('dragover').on('dragover', dragover);
      that.findDesignRoot().off('dragend').on('dragend', dragend);
      startDragShadowImg(e, el);
    }

    this.findDesignRoot().find(`[data-action=${constant.move}]`).attr('draggable', true);
    this.findDesignRoot().find(`[data-action=${constant.move}]`).off('dragstart').on('dragstart', dragstart);
  }

  bindDragFieldComponent(dragging) {
    let that = this, {root} = this, placeholder = undefined;
    let fieldComponent = this.getComponentName(dragging);
    if (!fieldComponent) return;
    fieldComponent = getFieldComponent(fieldComponent);
    if (!fieldComponent) return;

    function dragover(e) {
      let {target} = e;
      let el = null;
      el = getElementParentUntilHasRole(target, constant.field);
      el = el || getElementParentUntilHasRole(target, constant.placeholder);
      el = el || getElementParentUntilHasRole(target, constant.content);
      el = el || getElementParentUntilHasRole(target, constant.layout);
      el = el || getElementParentUntilHasRole(target, constant.designRoot);
      if (isRole(el, constant.placeholder)) {
        if (el.parentNode === that.findDesignRoot()[0]) {
          stop(e);
          return;
        } else {
          el = getElementParentUntilHasRole(el, constant.content);
        }
      }
      if (!el) {
        $(placeholder).remove();
        return;
      }
      placeholder = placeholder || createDraginRootPlaceholder();
      if (isRole(el, constant.designRoot)) {
        //拖拽进入了root
        // that.findDesignRoot().append(placeholder);

        let rect = target.getBoundingClientRect();
        if (rect.y + 20 > e.clientY) {
          //比较靠上
          if (that.findDesignRoot().children().first()[0] === dragging) {
            return;
          }
          that.findDesignRoot().prepend(placeholder);
        } else {
          //比较靠下
          if (that.findDesignRoot().children().last()[0] === dragging) {
            return;
          }
          that.findDesignRoot().append(placeholder);
        }
      }
      if (isRole(el, constant.field) || isRole(el, constant.layout)) {
        if (el.parentNode === that.findDesignRoot()[0]) {
          let rect = el.getBoundingClientRect();
          if (rect.y + 15 > e.clientY) {
            //比较靠上
            el.before(placeholder);
          } else {
            //比较靠下
            el.after(placeholder);
          }
        } else {
          $(placeholder).remove();
          return;
        }
      }
      if (isRole(el, constant.content)) {
        let layout = getElementParentUntilHasRole(el, constant.layout);
        let rect = layout.getBoundingClientRect();
        if (rect.y + 15 > e.clientY) {
          //比较靠上
          $(layout).before(placeholder);
        } else {
          //比较靠下
          // if ($(el).children().length === 0) {
          if (isEmptyContent(el)) {
            $(el).append(placeholder);
          }
        }
      }
      stop(e);
    }

    function dragend() {
      if (!placeholder || !placeholder.parentNode) return;
      fieldComponent.comp.createField().then(({el, config}) => {
        that.resolveNewFieldElement(config, el);
        that.addFieldConfig(config, placeholder);
        $(placeholder).replaceWith(el);
        that.reBind && that.reBind();
      }).catch(console.error);
      $(document.body).off('dragover');
      $(dragging).off('dragend');
    }

    $(document.body).off('dragover').on('dragover', dragover);
    $(dragging).off('dragend').on('dragend', dragend);
  }

  resolveNewFieldElement(config, el, rename = true) {
    if (rename) {
      let index = ++this.formDefinition.fieldLastIndex;
      config.fieldName = undefined;
      config.fieldTitleName = undefined;
      config.label += ` ${index}`;
    }
    $(el).attr('data-role', 'field');
    $(el).attr('data-field-id', config.id);
    $(el).attr('draggable', true);
    el.append(createFieldBarWrapper());
  }

  bindDragBarAction() {
    this.findDesignRoot().find('[data-role=' + constant.dragBarAction + ']').off('click').on('click', ({target}) => {
      target = getElementParentUntilHasRole(target, 'drag-bar-action');
      if (!target) return;
      let action = getBarAction(target);
      this[action] && this[action](target);
    });
  }

  bindSelectField() {
    let that = this;

    function click(e) {
      let {target} = e;
      let el = getElementParentUntilHasRole(target, constant.field);
      if (!el) return;
      let fieldId = getFieldId(el);
      if (!fieldId) return;
      setSelectFieldStyle(el);
      that.config && that.config.selectField && that.config.selectField(fieldId);
      that.bindClearSelectedField();
    }

    this.findDesignRoot().find('[data-role=' + constant.field + ']').off('click').on('click', click);
    this.findDesignRoot().find('[data-role=' + constant.field + ']').off('dblclick').on('dblclick', stop);
  }

  findFieldContainer() {
    return $(this.root).find('[data-role=' + constant.fieldContainer + ']');
  }

  findDesignRoot() {
    return $(this.root).find('[data-role=' + constant.designRoot + ']');
  }

  getComponentName(el) {
    return $(el).attr('data-component');
  }

  addFieldConfig(config, placeholder) {
    if (config.viewComponent) {
      let view = this.getSelectedView();
      if (view) {
        view.components.push(config);
      }
    } else {
      let layout = getElementParentUntilHasRole(placeholder, constant.layout);
      if (!layout || !isSubTable(layout)) {
        this.formDefinition.fields.push(config);
        return;
      }
      let tr = getElementParentUntilTag(placeholder, 'tr');
      if (getSubTableRole(tr) !== constant.subTableBody) {
        this.formDefinition.fields.push(config);
        return;
      }
      let subTableId = getSubTableId(layout);
      let subForm = this.formDefinition.subForms.find(s => s.id === subTableId);
      if (subForm) {
        subForm.fields.push(config);
      }
    }
  }

  getSelectedView() {
    return this.formDefinition.views.find(v => v.id === this.formDefinition.selectedView) || {components: []};
  }

  bindDragLayoutComponent(dragging) {
    let that = this, placeholder = undefined;
    let fieldComponent = this.getComponentName(dragging);
    if (!fieldComponent) return;
    fieldComponent = getFieldComponent(fieldComponent);

    function dragend() {
      if (!placeholder || !placeholder.parentNode) return;
      fieldComponent.comp.createField().then(({el, config}) => {
        that.resolveNewLayoutElement(config, el);
        $(placeholder).replaceWith(el);
        that.resolveLayoutWidth(el);
        that.reBind && that.reBind();
      }).catch(() => {
        $(placeholder).remove();
      });
      $(document.body).off('dragover');
      $(dragging).off('dragend');
    }

    function dragover(e) {
      let {target} = e;
      let el = getElementParentUntilHasRole(target, constant.placeholder);
      el = el || getElementParentUntilHasRole(target, constant.field);
      el = el || getElementParentUntilHasRole(target, constant.layout);
      el = el || getElementParentUntilHasRole(target, constant.designRoot);
      if (!el) {
        $(placeholder).remove();
        return;
      }
      if (isRole(el, constant.placeholder)) {
        stop(e);
        return;
      }
      placeholder = placeholder || createDraginRootPlaceholder();
      if (isRole(el, constant.field) || isRole(el, constant.layout)) {
        if (el.parentNode === that.findDesignRoot()[0]) {
          //layout拖拽到了字段上, 并且字段的上一级是root
          let rect = el.getBoundingClientRect();
          if (rect.y + 15 > e.clientY) {
            //比较靠上
            $(el).before(placeholder);
          } else {
            //比较靠下
            $(el).after(placeholder);
          }
        } else {
          el = getElementParentUntilHasRole(target, constant.layout);
        }
      }
      if (!el) return;
      if (isRole(el, constant.designRoot)) {
        //拖拽进入了root
        // that.findDesignRoot().append(placeholder);

        let rect = target.getBoundingClientRect();
        if (rect.y + 20 > e.clientY) {
          //比较靠上
          if (that.findDesignRoot().children().first()[0] === dragging) {
            return;
          }
          that.findDesignRoot().prepend(placeholder);
        } else {
          //比较靠下
          if (that.findDesignRoot().children().last()[0] === dragging) {
            return;
          }
          that.findDesignRoot().append(placeholder);
        }
      }
      stop(e);
    }

    $(document.body).off('dragover').on('dragover', dragover);
    $(dragging).off('dragend').on('dragend', dragend);
  }

  bindDragFieldDefinition(dragging) {
    dragging = getElementParentUntilHasRole(dragging, constant.fieldDefinition);
    if (!dragging) return;
    let fieldId = getFieldId(dragging), that = this;
    let config = getFieldConfigById(fieldId, this.formDefinition);
    let fieldComponent = getFieldComponent(config.component);
    if (!config || !fieldComponent) return;
    let len = this.findDesignRoot().find('[data-field-id=' + fieldId + ']').length;
    if (len >= 1) return;
    let placeholder = undefined;

    function dragend() {
      if (!placeholder || !placeholder.parentNode) return;
      fieldComponent.comp.createFieldElement().then(el => {
        el = createFieldWrapper(el);
        that.resolveNewFieldElement(config, el, false);
        $(placeholder).replaceWith(el);
        that.reBind && that.reBind();
      });
      $(document.body).off('dragover');
      $(dragging).off('dragend');
    }

    function dragover(e) {
      let {target} = e;
      let el = getElementParentUntilHasRole(target, constant.field);
      el = el || getElementParentUntilHasRole(target, constant.placeholder);
      el = el || getElementParentUntilHasRole(target, constant.content);
      el = el || getElementParentUntilHasRole(target, constant.layout);
      el = el || getElementParentUntilHasRole(target, constant.designRoot);
      if (isRole(el, constant.placeholder)) {
        if (el.parentNode === that.findDesignRoot()[0]) {
          stop(e);
          return;
        } else {
          el = getElementParentUntilHasRole(el, constant.content);
        }
      }
      if (!el) {
        $(placeholder).remove();
        return;
      }
      placeholder = placeholder || createDraginRootPlaceholder();
      if (isRole(el, constant.designRoot)) {
        if (isSubFormField(fieldId, that.formDefinition)) {
          $(placeholder).remove();
          return;
        }
        // $(el).append(placeholder);

        let rect = target.getBoundingClientRect();
        if (rect.y + 20 > e.clientY) {
          //比较靠上
          if (that.findDesignRoot().children().first()[0] === dragging) {
            return;
          }
          that.findDesignRoot().prepend(placeholder);
        } else {
          //比较靠下
          if (that.findDesignRoot().children().last()[0] === dragging) {
            return;
          }
          that.findDesignRoot().append(placeholder);
        }
      }
      if (isRole(el, constant.field) || isRole(el, constant.layout)) {
        if (isSubFormField(fieldId, that.formDefinition)) {
          $(placeholder).remove();
          return;
        }
        if (el.parentNode === that.findDesignRoot()[0]) {
          let rect = el.getBoundingClientRect();
          if (rect.y + 15 > e.clientY) {
            //比较靠上
            el.before(placeholder);
          } else {
            //比较靠下
            el.after(placeholder);
          }
        } else {
          $(placeholder).remove();
          return;
        }
      }

      if (isRole(el, constant.content)) {
        let layout = getElementParentUntilHasRole(el, constant.layout);
        let rect = layout.getBoundingClientRect();
        if (rect.y + 15 > e.clientY) {
          //比较靠上
          if (isSubFormField(fieldId, that.formDefinition)) {
            $(placeholder).remove();
            return;
          }
          layout.before(placeholder);
        } else {
          //比较靠下
          // if (!$(el).children().length) {
          if (!canDragin(el, fieldId, that.formDefinition)) {
            $(placeholder).remove();
            return;
          }
          if (isEmptyContent(el)) {
            $(el).append(placeholder);
          }
        }
      }
      stop(e);
    }

    $(document.body).off('dragover').on('dragover', dragover);
    $(dragging).off('dragend').on('dragend', dragend);
  }

  removeField(bar) {
    Modal.confirm({
      title: '确定删除吗?',
      content: '删除后不可恢复, 确定删除吗?',
      okText: '确定',
      cancelText: '取消',
      onOk: () => {
        let field = getElementParentUntilHasRole(bar, constant.field);
        $(field).remove();
      }
    });
  }

  removeLayout(bar) {
    Modal.confirm({
      title: '确定删除吗?',
      content: '删除表格后, 表格中的组件也会删除, 并且不可恢复, 确定删除吗?',
      okText: '确定',
      cancelText: '取消',
      onOk: () => {
        let layout = getElementParentUntilHasRole(bar, constant.layout);
        $(layout).remove();
      }
    });
  }

  resolveLayoutWidth(bar) {
    let layout = getElementParentUntilHasRole(bar, constant.layout);
    let cols = $(layout).find('col'), allWidth = 0;
    for (let i = 0; i < cols.length; i++) {
      allWidth += cols[i].offsetWidth;
    }
    let rootWidth = this.findDesignRoot().width() - 6;
    for (let i = 0; i < cols.length; i++) {
      let temp = (cols[i].offsetWidth / allWidth) * rootWidth;
      $(cols[i]).width(temp);
    }

    for (let i = 0; i < 1; i++) {
      $(layout).find('table').css('table-layout', 'auto');
      $(layout).find('table').css('width', '100%');
      let cols = $(layout).find('col');
      for (let i = 0; i < cols.length; i++) {
        $(cols[i]).css('width', `${$(cols[i]).width()}px`);
      }
      $(layout).find('table').css('table-layout', '');
      $(layout).find('table').css('width', '');
    }
  }

  resolveNewLayoutElement(config, el) {
    let layoutType = config.layoutType || constant.layout;
    $(el).attr('data-layout-type', layoutType);
    $(el).attr('data-role', constant.layout);
    $(el).append(createLayoutBarContainer());
    if (layoutType === constant.subTable) {
      this.createNewSubTable(el, config);
    }
  }

  createNewSubTable(el, config) {
    let subForm = createSubTable(this.formDefinition);
    $(el).attr('data-sub-form-id', subForm.id);
  }

  getParentElementUntilContent(el) {
    while (el && el.tagName !== 'TD') el = el.parentNode;
    // return $(el).find('.content')[0];
    return el;
  }

  setSelectedField(selectedField) {
    setSelectFieldStyle(this.findDesignRoot().find(`[data-field-id=${selectedField}]`)[0]);
    this.bindClearSelectedField();
  }

  bindClearSelectedField() {
    let that = this;

    function mousedown({target}) {
      if (getElementParentUntilHasRole(target, constant.ignoreSelectField)) {
        return;
      }
      setSelectFieldStyle();
      $(window).off('mousedown', mousedown);
      that.config && that.config.selectField && that.config.selectField(undefined);
    }

    $(window).on('mousedown', mousedown);
  }

  bindFieldTitles() {
    let fields = this.formDefinition.fields || [];
    fields.forEach(f => {
      let field = this.getFieldById(f.id);
      if (!field) return;
      let {component} = f;
      component = getFieldComponent(component);
      if (!component) return;
      component.comp.setFieldTitle(field, f);
    });

    this.formDefinition.subForms.forEach(f => {
      f.fields.forEach(f => {
        let field = this.getFieldById(f.id);
        if (!field) return;
        let {component} = f;
        component = getFieldComponent(component);
        if (!component) return;
        component.comp.setFieldTitle(field, f);
      });
    });
    let view = this.getSelectedView();
    view.components.forEach(f => {
      let field = this.getFieldById(f.id);
      if (!field) return;
      let {component} = f;
      component = getFieldComponent(component);
      if (!component) return;
      component.comp.setFieldTitle(field, f);
    });
  }

  bindDragSubFormDefinition() {
    let subForm = undefined, that = this, subFormId = undefined;
    let dragging = undefined, placeholder = undefined;

    function dragend() {
      if (!placeholder || !placeholder.parentNode) return;
      createSubTableByConfig(subForm, el => {
        if (!el) {
          $(placeholder).remove();
        } else {
          $(placeholder).replaceWith(el);
        }
        that.resolveLayoutWidth(el);
        that.reBind && that.reBind();
      });
      $(document.body).off('dragover');
      $(dragging).off('dragend');
    }

    function dragover(e) {
      let {target} = e;
      let el = getElementParentUntilHasRole(target, constant.placeholder);
      el = el || getElementParentUntilHasRole(target, constant.layout);
      el = el || getElementParentUntilHasRole(target, constant.field);
      el = el || getElementParentUntilHasRole(target, constant.designRoot);
      if (!el) {
        $(placeholder).remove();
        return;
      }
      if (isRole(el, constant.placeholder)) {
        stop(e);
        return;
      }
      placeholder = placeholder || createDraginRootPlaceholder();
      if (isRole(el, constant.layout) || isRole(el, constant.field)) {
        var rect = el.getBoundingClientRect();
        if (rect.y + 15 >= e.clientY) {
          // 比较靠上
          $(el).before(placeholder);
        } else {
          // 比较靠下
          $(el).after(placeholder);
        }
      }
      if (isRole(el, constant.designRoot)) {
        // $(el).append(placeholder);
        let rect = target.getBoundingClientRect();
        if (rect.y + 20 > e.clientY) {
          //比较靠上
          if (that.findDesignRoot().children().first()[0] === dragging) {
            return;
          }
          that.findDesignRoot().prepend(placeholder);
        } else {
          //比较靠下
          if (that.findDesignRoot().children().last()[0] === dragging) {
            return;
          }
          that.findDesignRoot().append(placeholder);
        }
      }
      stop(e);
    }

    function dragstart({target}) {
      dragging = target;
      let el = getElementParentUntilHasRole(target, constant.subFormDefinition);
      if (!el) return;
      subFormId = getSubTableId(el);
      if (that.findDesignRoot().find('div[data-sub-form-id=' + subFormId + ']').length) return;

      subForm = getSubFormById(subFormId, that.formDefinition);
      if (!subFormId || !subForm) return;

      $(document.body).off('dragover').on('dragover', dragover);
      $(dragging).off('dragend').on('dragend', dragend);
    }

    this.findFieldContainer()
    .find('*[data-role=' + constant.subFormDefinition + ']')
    .attr('draggable', true)
    .off('dragstart').on('dragstart', dragstart);
  }

  bindCustomComponents() {
    function dragstart() {

    }

    this.findFieldContainer().find('div[data-role=' + constant.customComponent + ']').off('dragstart').on('dragstart', dragstart);
  }

  getFieldById(id) {
    return this.findDesignRoot().find('[data-field-id=' + id + ']')[0];
  }

  getFieldConfigById(id) {
    let list = this.formDefinition.fields || [];
    return list.find(item => item.id === id);
  }

  removeRedundantFields() {
    if (!this.formDefinition) return;
    let fieldConfigs = this.formDefinition.fields || [];

    let fields = this.findDesignRoot().find('[data-role=field]') || [];
    for (let i = 0; i < fields.length; i++) {
      let field = fields[i];
      let fieldId = getFieldId(field);

      let finded = false;
      if (fieldConfigs.findIndex(f => f.id === fieldId) !== -1) {
        finded = true;
      }
      this.formDefinition.subForms.forEach(f => {
        if (f.fields.findIndex(f => f.id === fieldId) !== -1) {
          finded = true;
        }
      });
      if (this.getSelectedView().components.findIndex(c => c.id === fieldId) !== -1) {
        finded = true;
      }
      if (!finded) {
        debugger
        $(field).remove();
      }
    }
    let tbodies = this.findDesignRoot().find('tbody');
    for (let i = 0; i < tbodies.length; i++) {
      let tbody = tbodies[i];
      let tds = $(tbody).find('td');
      if(tds.length <= 0) {
        let field = getElementParentUntilHasRole(tbody, constant.layout);
        $(field).remove();
      }
    }
  }

  removeRedundantSubForms() {
    let subFormsElements = this.findDesignRoot().find('div[data-layout-type=' + constant.subTable + ']');
    let subForms = this.formDefinition.subForms || [];
    for (let i = 0; i < subFormsElements.length; i++) {
      let subFormId = getSubFormIdByLayoutElement(subFormsElements[i]);
      if (!subForms.find(s => s.id === subFormId)) {
        $(subFormsElements[i]).remove();
      }
    }
  }

  resolveSubFormButtonContainer() {
    let cs = this.findDesignRoot().find('[data-sub-table-role=sub-form-button-container]');
    for (let i = 0; i < cs.length; i++) {
      let td = cs[i], table = td;
      while (table && table.tagName !== 'TABLE') table = table.parentNode;
      if(!table) continue;
      let cols = $(table).find('col');
      let tds = $(td).parent().find('td');
      for (let j = 0; j < tds.length; j++) {
        hideTd(tds[j]);
      }
      showTd(td);
      $(td).attr('colspan', cols.length);
    }
  }
}

export {
  constant
};